/******************************************************************************/
/* @ All Rights Reserved Copyright (C) 2014 broada,Ltd.                       */
/*                                                                            */
/*  NAME      = cups_comm.c                                                    */
/*  NOTE      = TDS 请求解析                                                  */
/*  DATE      = 2015/03/19 by zhengxd                                         */
/******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <math.h>
#include <stdint.h>
#include <limits.h>

#include "cups_comm.h"
#define CUPS_MAX_NUM_LEN         13

char arr_field_name[128][128] =
{
    "",                                           /* 1 */
    "PrimaryAccountNumber",                       /* 2 */
    "ProcessingCode",                             /* 3 */
    "TransactionsAmount",                         /* 4 */
    "SettlementAmount",                           /* 5 */
    "CardholderBillingAmount",                    /* 6 */
    "TransmissionDateTime",                       /* 7 */
    "",                                           /* 8 */
    "SettlementConversionRate",                   /* 9 */
    "CardholderBillingConversionRate",            /* 10 */
    "SystemTraceAuditNumber",                     /* 11 */
    "LocalTransactionTime",                       /* 12 */
    "LocalTransactionDate",                       /* 13 */
    "ExpirationDate",                             /* 14 */
    "SettlementDate",                             /* 15 */
    "ConversionDate",                             /* 16 */
    "",                                           /* 17 */
    "MerchantType",                               /* 18 */
    "AcquiringInstitutionCountryCode",            /* 19 */
    "",                                           /* 20 */
    "",                                           /* 21 */
    "PointOfServiceEntryModeCode",                /* 22 */
    "CardSequenceNumber",                         /* 23 */
    "",                                           /* 24 */
    "PointOfServiceConditionCode",                /* 25 */
    "PointOfServicePINCaptureCode",               /* 26 */
    "",                                           /* 27 */
    "TransactionFeeAmount",                       /* 28 */
    "",                                           /* 29 */
    "",                                           /* 30 */
    "",                                           /* 31 */
    "AcquiringInstitutionIdentificationCode",     /* 32 */
    "ForwardingInstitutionIdentificationCode",    /* 33 */
    "",                                           /* 34 */
    "Track2Data",                                 /* 35 */
    "Track3Data",                                 /* 36 */
    "RetrievalReferenceNumber",                   /* 37 */
    "AuthorizationIdentificationResponse",        /* 38 */
    "ResponseCode",                               /* 39 */
    "",                                           /* 40 */
    "CardAcceptorTerminalIdentification",         /* 41 */
    "CardAcceptorIdentificationCode",             /* 42 */
    "LocationCardAcceptorName",                   /* 43 */
    "AdditionResponseData",                       /* 44 */
    "Track1Data",                                 /* 45 */
    "",                                           /* 46 */
    "",                                           /* 47 */
    "AdditionDataPrivate",                        /* 48 */
    "TransactionCurrencyCode",                    /* 49 */
    "SettlementCurrencyCode",                     /* 50 */
    "CardholderBillingCurrencyCode",              /* 51 */
    "PinData",                                    /* 52 */
    "SecurityRelatedControlInformation",          /* 53 */
    "AdditionalAmounts",                          /* 54 */
    "ICCSystemRelatedData",                       /* 55 */
    "",                                           /* 56 */
    "AdditionalDataPrivate",                      /* 57 */
    "ICDataReserved",                             /* 58 */
    "DetailInquiring",                            /* 59 */
    "Reserved",                                   /* 60 */
    "CardholderAuthenticationInformation",        /* 61 */
    "SwitchingData",                              /* 62 */
    "FinacialNetworkData",                        /* 63 */
    "",                                           /* 64 */
    "",                                           /* 65 */
    "",                                           /* 66 */
    "",                                           /* 67 */
    "",                                           /* 68 */
    "",                                           /* 69 */
    "NetworkManagementInformationCode",           /* 70 */
    "",                                           /* 71 */
    "",                                           /* 72 */
    "",                                           /* 73 */
    "",                                           /* 74 */
    "",                                           /* 75 */
    "",                                           /* 76 */
    "",                                           /* 77 */
    "",                                           /* 78 */
    "",                                           /* 79 */
    "",                                           /* 80 */
    "",                                           /* 81 */
    "",                                           /* 82 */
    "",                                           /* 83 */
    "",                                           /* 84 */
    "",                                           /* 85 */
    "",                                           /* 86 */
    "",                                           /* 87 */
    "",                                           /* 88 */
    "",                                           /* 89 */
    "OriginalDataElements",                       /* 90 */
    "",                                           /* 91 */
    "",                                           /* 92 */
    "",                                           /* 93 */
    "",                                           /* 94 */
    "",                                           /* 95 */
    "MessageSecurityCode",                        /* 96 */
    "",                                           /* 97 */
    "",                                           /* 98 */
    "",                                           /* 99 */
    "ReceivingInstitutionIdentificationCode",     /* 100 */
    "",                                           /* 101 */
    "AccountIdentification1",                     /* 102 */
    "AccountIdentification2",                     /* 103 */
    "",                                           /* 104 */
    "",                                           /* 105 */
    "",                                           /* 106 */
    "",                                           /* 107 */
    "",                                           /* 108 */
    "",                                           /* 109 */
    "",                                           /* 110 */
    "",                                           /* 111 */
    "",                                           /* 112 */
    "",                                           /* 113 */
    "",                                           /* 114 */
    "",                                           /* 115 */
    "",                                           /* 116 */
    "",                                           /* 117 */
    "",                                           /* 118 */
    "",                                           /* 119 */
    "",                                           /* 120 */
    "CUPSReserved",                               /* 121 */
    "AcquiringInstitutionReserved",               /* 122 */
    "IssuerInstitutionReserved",                  /* 123 */
    "",                                           /* 124 */
    "",                                           /* 125 */
    "",                                           /* 126 */
    "",                                           /* 127 */
    "MessageAuthenticationCode"                   /* 128 */
};

/*******************************************************************************
*  FUNC     :  释放field
*  ARGS     :  p_st_node(Frlist_node)
*  RTN      :  void
*  NOTE     :
*******************************************************************************/
void cups_free(char **pp_value)
{
    if (pp_value == NULL || *pp_value == NULL)
    {
        return;
    }

    frfree(*pp_value);
    *pp_value = NULL;

    return;
}

/*******************************************************************************
*  FUNC     :  取得numbers
*  ARGS     :  p_st_data(数据信息)
*           :  p_dest_id(目的ID)
*           :  p_src_id(源ID)
*           :  p_trans_info(交易信息)
*           :  p_reject_code(拒绝码)
*  RTN      :  FR_SUCC  (success)
*              FR_FAIL  (failed)
*  NOTE     :  p_st_data必须不为NULL,p_dest_id和p_src_id的size必须大于11,
*              p_trans_info的size必须大于8,p_reject_code的size必须大于5,
*              p_msg_type的size必须大于4,p_bitmap的size必须大于16.
*******************************************************************************/
int cups_parse_head(Frbyte_Packet *p_st_data
                    , char *p_dest_id
                    , char *p_src_id
                    , char *p_trans_info
                    , char *p_msg_type
                    , char *p_bitmap
                    , unsigned int *p_bitmap_len
                    , unsigned int *p_rej_code)
{
    int i_ret = FR_SUCC;
    uint8_t u8_word = 0;

    if (bytebuff_remaining(p_st_data) < CUPS_TPDU_LEN + CUPS_MSG_TP_LEN + CUPS_MAIN_MAP_LEN)
    {
        frdbg("header length is less than 46!\n");
        return FR_FAIL;
    }

    /* 取得报文头长度 */
    i_ret = bytebuff_get_char(p_st_data, &u8_word);
    if (i_ret != FR_SUCC || u8_word != CUPS_TPDU_LEN)
    {
        frdbg("header length is not 46!\n");
        return FR_FAIL;
    }
    /* 跳过头标识和版本号+长度位 */
    i_ret = bytebuff_skip(p_st_data, 1 + CUPS_LEN_LEN);
    if (i_ret != FR_SUCC)
    {
        frdbg("skip header flag and version failed!\n");
        return FR_FAIL;
    }

    /* 取得目的ID */
    i_ret = bytebuff_get_bytes(p_st_data, p_dest_id, CUPS_ID_LEN);
    if (i_ret != FR_SUCC)
    {
        frdbg("get Destination Station ID failed!\n");
        return FR_FAIL;
    }
    p_dest_id[CUPS_ID_LEN] = '\0';
    frrtrim(p_dest_id);

    /* 取得源ID */
    i_ret = bytebuff_get_bytes(p_st_data, p_src_id, CUPS_ID_LEN);
    if (i_ret != FR_SUCC)
    {
        frdbg("get Source Station ID failed!\n");
        return FR_FAIL;
    }
    p_src_id[CUPS_ID_LEN] = '\0';
    frrtrim(p_src_id);

    /* 跳过保留使用位,批次号 */
    i_ret = bytebuff_skip(p_st_data, 3 + 1);
    if (i_ret != FR_SUCC)
    {
        frdbg("skip Reserved-for-Use and Batch-Number failed!\n");
        return FR_FAIL;
    }
    /* 取得交易信息 */
    i_ret = bytebuff_get_bytes(p_st_data, p_trans_info, CUPS_TRANS_INFO_LEN);
    if (i_ret != FR_SUCC)
    {
        frdbg("get tarnscation information failed!\n");
        return FR_FAIL;
    }
    p_trans_info[CUPS_TRANS_INFO_LEN] = '\0';
    /* 跳过用户信息 */
    i_ret = bytebuff_skip(p_st_data, 1);
    if (i_ret != FR_SUCC)
    {
        frdbg("skip user information failed!\n");
        return FR_FAIL;
    }

    /* 取得长度 */
    i_ret = cups_get_len(p_st_data, CUPS_REJ_CODE_LEN, p_rej_code);
    if (i_ret != FR_SUCC)
    {
        frdbg("get length failed!\n");
        return FR_FAIL;
    }

    /* 取得报文类型 */
    i_ret = bytebuff_get_bytes(p_st_data, p_msg_type, CUPS_MSG_TP_LEN);
    if (i_ret != FR_SUCC)
    {
        frdbg("get Source Station ID failed!\n");
        return FR_FAIL;
    }
    p_msg_type[CUPS_MSG_TP_LEN] = '\0';

    /* 取得主位图 */
    i_ret = bytebuff_get_bytes(p_st_data, p_bitmap, CUPS_MAIN_MAP_LEN);
    if (i_ret != FR_SUCC)
    {
        frdbg("get Source Station ID failed!\n");
        return FR_FAIL;
    }
    p_bitmap[CUPS_MAIN_MAP_LEN] = '\0';
    *p_bitmap_len = CUPS_MAIN_MAP_LEN;

    /* 取得第二位图 */
    if (p_bitmap[0] & 0x80)
    {
        i_ret = bytebuff_get_bytes(p_st_data, p_bitmap + CUPS_MAIN_MAP_LEN, CUPS_SUB_MAP_LEN);
        if (i_ret != FR_SUCC)
        {
            frdbg("get Source Station ID failed!\n");
            return FR_FAIL;
        }
        p_bitmap[CUPS_MAP_MAX_LEN] = '\0';
        *p_bitmap_len += CUPS_SUB_MAP_LEN;
    }

    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  释放field
*  ARGS     :  ui_index(域序列)
*  RTN      :  域名称
*  NOTE     :
*******************************************************************************/
char *cups_ret_value(unsigned int ui_index)
{
    return arr_field_name[ui_index];
}

/*******************************************************************************
*  FUNC     :  释放field
*  ARGS     :  ui_rej_code(拒绝码)
*  RTN      :  error message
*  NOTE     :
*******************************************************************************/
char* cups_error_msg(unsigned int ui_rej_code)
{
    char *p_err_msg = NULL;

    switch(ui_rej_code)
    {
        case 0:
            break;

        case 15:
            p_err_msg = frstrdup("报文头长度中出现非法字符");
            break;

        case 25:
            p_err_msg = frstrdup("头标识和版本中出现非法字符");
            break;

        case 35:
            p_err_msg = frstrdup("报文总长度中出现非数字字符");
            break;

        case 45:
            p_err_msg = frstrdup("目的 ID 中出现非法字字符");
            break;

        case 55:
            p_err_msg = frstrdup("源 ID 中出现非法字字符");
            break;

        case 65:
            p_err_msg = frstrdup("保留使用域中出现非法字符");
            break;

        case 75:
            p_err_msg = frstrdup("批次号中出现非数字字符");
            break;

        case 85:
            p_err_msg = frstrdup("保留给银联内部使用中出现非法字符");
            break;

        case 10005:
            p_err_msg = frstrdup("报文类型标识符中出现非数字字符/报文类型标识符非法");
            break;

        case 10023:
            p_err_msg = frstrdup("主账号长度域中出现非法字符");
            break;

        case 10024:
            p_err_msg = frstrdup("主账号长度值大于19");
            break;

        case 10025:
            p_err_msg = frstrdup("主账号中出现非法字符");
            break;

        case 10035:
            p_err_msg = frstrdup("非法交易处理码或非法字符");
            break;

        case 10045:
            p_err_msg = frstrdup("交易金额中出现非法字符");
            break;

        case 10055:
            p_err_msg = frstrdup("清算金额中出现非法字符");
            break;

        case 10065:
            p_err_msg = frstrdup("持卡人扣账金额中出现非法字符");
            break;

        case 10075:
            p_err_msg = frstrdup("传输日期和时间中出现非法数字或字符");
            break;

        case 10095:
            p_err_msg = frstrdup("清算汇率中出现非法字符");
            break;

        case 10105:
            p_err_msg = frstrdup("持卡人扣账汇率金额中出现非数字字符");
            break;

        case 10115:
            p_err_msg = frstrdup("系统跟踪号中出现非数字字符");
            break;

        case 10125:
            p_err_msg = frstrdup("受卡方所在地时间中出现非法数字或字符");
            break;

        case 10135:
            p_err_msg = frstrdup("受卡方所在地日期中出现非法数字或字符");
            break;

        case 10145:
            p_err_msg = frstrdup("卡有效期中出现非法数字或字符");
            break;

        case 10155:
            p_err_msg = frstrdup("清算日期中出现非法数字或字符");
            break;

        case 10165:
            p_err_msg = frstrdup("兑换日期中出现非法数字或字符");
            break;

        case 10185:
            p_err_msg = frstrdup("商户类型中出现非法字符");
            break;

        case 10195:
            p_err_msg = frstrdup("代理机构国家代码中出现非法字符");
            break;

        case 10225:
            p_err_msg = frstrdup("服务点输入方式码中出现非法字符");
            break;

        case 10235:
            p_err_msg = frstrdup("卡顺序号中出现非法字符");
            break;

        case 10255:
            p_err_msg = frstrdup("服务点条件代码中出现非法字符");
            break;

        case 10265:
            p_err_msg = frstrdup("服务点 PIN 获取码中出现非法字符");
            break;

        case 10285:
            p_err_msg = frstrdup("交易费金额中出现非数字字符");
            break;

        case 10295:
            p_err_msg = frstrdup("清算费金额中出现非数字字符");
            break;

        case 10315:
            p_err_msg = frstrdup("清算处理费金额中出现非数字字符");
            break;

        case 10323:
            p_err_msg = frstrdup("长度域中出现非法字符");
            break;

        case 10324:
            p_err_msg = frstrdup("长度值大于11");
            break;

        case 10325:
            p_err_msg = frstrdup("受理机构标识码中出现非法字符");
            break;

        case 10333:
            p_err_msg = frstrdup("长度域中出现非法字符");
            break;

        case 10334:
            p_err_msg = frstrdup("长度值大于11");
            break;

        case 10335:
            p_err_msg = frstrdup("发送机构标识码中出现非法字符");
            break;

        case 10345:
            p_err_msg = frstrdup("扩展主帐号中出现非法字符");
            break;

        case 10353:
            p_err_msg = frstrdup("长度域中出现非法字符");
            break;

        case 10354:
            p_err_msg = frstrdup("长度值大于37");
            break;

        case 10355:
            p_err_msg = frstrdup("非法第二磁道内容或出现非法字符");
            break;

        case 10363:
            p_err_msg = frstrdup("长度域中出现非法字符");
            break;

        case 10364:
            p_err_msg = frstrdup("长度值大于104");
            break;

        case 10365:
            p_err_msg = frstrdup("非法第三磁道内容或出现非法字符");
            break;

        case 10375:
            p_err_msg = frstrdup("检索参考号中出现非法字符");
            break;

        case 10385:
            p_err_msg = frstrdup("授权标识响应中出现非法字符");
            break;

        case 10395:
            p_err_msg = frstrdup("应答码中出现非法字符");
            break;

        case 10405:
            p_err_msg = frstrdup("服务限制代码中出现非法字符");
            break;

        case 10415:
            p_err_msg = frstrdup("非法字符");
            break;

        case 10425:
            p_err_msg = frstrdup("非法字符");
            break;

        case 10435:
            p_err_msg = frstrdup("非法字符");
            break;

        case 10443:
            p_err_msg = frstrdup("长度域中出现非法字符");
            break;

        case 10444:
            p_err_msg = frstrdup("长度值大于25");
            break;

        case 10453:
            p_err_msg = frstrdup("长度域中出现非法字符");
            break;

        case 10454:
            p_err_msg = frstrdup("长度值大于79");
            break;

        case 10455:
            p_err_msg = frstrdup("非法字符");
            break;

        case 10483:
            p_err_msg = frstrdup("长度域中出现非法字符");
            break;

        case 10484:
            p_err_msg = frstrdup("长度值大于512");
            break;

        case 10485:
            p_err_msg = frstrdup("非法字符");
            break;

        case 10495:
            p_err_msg = frstrdup("交易货币代码中出现非法字符");
            break;

        case 10505:
            p_err_msg = frstrdup("清算货币代码中出现非法字符");
            break;

        case 10515:
            p_err_msg = frstrdup("持卡人帐户货币代码中出现非数字字符");
            break;

        case 10535:
            p_err_msg = frstrdup("安全控制信息中出现非法字符");
            break;

        case 10543:
            p_err_msg = frstrdup("长度域中出现非法字符");
            break;

        case 10544:
            p_err_msg = frstrdup("长度值不等于40");
            break;

        case 10545:
            p_err_msg = frstrdup("附加金额中出现非法字符");
            break;

        case 10573:
            p_err_msg = frstrdup("长度域中出现非法字符");
            break;

        case 10574:
            p_err_msg = frstrdup("长度值大于100");
            break;

        case 10575:
            p_err_msg = frstrdup("非法字符");
            break;

        case 10583:
            p_err_msg = frstrdup("长度域中出现非法字符");
            break;

        case 10584:
            p_err_msg = frstrdup("长度值大于100");
            break;

        case 10585:
            p_err_msg = frstrdup("非法字符");
            break;

        case 10593:
            p_err_msg = frstrdup("长度域中出现非法字符");
            break;

        case 10594:
            p_err_msg = frstrdup("长度值大于600");
            break;

        case 10595:
            p_err_msg = frstrdup("非法字符");
            break;

        case 10603:
            p_err_msg = frstrdup("长度域中出现非法字符");
            break;

        case 10604:
            p_err_msg = frstrdup("长度值大于100");
            break;

        case 10605:
            p_err_msg = frstrdup("非法字符/非法内容");
            break;

        case 10613:
            p_err_msg = frstrdup("长度域中出现非法字符");
            break;

        case 10614:
            p_err_msg = frstrdup("长度值大于60");
            break;

        case 10623:
            p_err_msg = frstrdup("长度域中出现非法字符");
            break;

        case 10624:
            p_err_msg = frstrdup("长度值大于 200");
            break;

        case 10625:
            p_err_msg = frstrdup("银联处理中心数据中出现非法字符");
            break;

        case 10633:
            p_err_msg = frstrdup("长度域中出现非法字符");
            break;

        case 10634:
            p_err_msg = frstrdup("长度值大于500");
            break;

        case 10635:
            p_err_msg = frstrdup("私有使用位元中出现非法字符");
            break;

        case 10665:
            p_err_msg = frstrdup("清算代码非法");
            break;

        case 10705:
            p_err_msg = frstrdup("网络管理代码中出现非法代码");
            break;

        case 10905:
            p_err_msg = frstrdup("原始数据元中出现非法字符");
            break;

        case 10955:
            p_err_msg = frstrdup("替换金额中出现非法字符");
            break;

        case 20000:
            p_err_msg = frstrdup("银联处理中心系统忙，请求未被处理");
            break;

        case 20001:
            p_err_msg = frstrdup("银联处理中心出错，交易被拒绝");
            break;

        case 20002:
            p_err_msg = frstrdup("银联处理中心处于灾备切换状态中");
            break;

        case 9990:
            p_err_msg = frstrdup("银联处理中心无法对收到的报文进行拆包处理或虽然拆包成功，但却无法识别交易类型");
            break;

        case 9991:
            p_err_msg = frstrdup("无法识别定义的卡介质种类");
            break;

        default:
            p_err_msg = frstrdup("unknow error");
            break;
    }

    return p_err_msg;
}

/*******************************************************************************
*  FUNC     :  释放field
*  ARGS     :  p_st_node(Frlist_node)
*  RTN      :  void
*  NOTE     :
*******************************************************************************/
void cups_field_free(cups_field_info **pp_st_field)
{
    if (pp_st_field == NULL || *pp_st_field == NULL)
    {
        return;
    }

    cups_field_info *p_st_field = *pp_st_field;

    if (p_st_field->p_field_value)
    {
        frfree(p_st_field->p_field_value);
    }
    frfree(p_st_field);

    *pp_st_field = NULL;
    return;
}

/*******************************************************************************
*  FUNC     :  创建field node
*  ARGS     :  ui_field_index (域号)
*           :  p_value (域值)
*           :  pp_st_node (出力节点)
*  RTN      :  FR_SUCC  (success)
*              FR_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
FR_STATIC int __cups_create_field(unsigned int ui_field_index
                                  , char *p_value
                                  , Frlist_node **pp_st_node)
{
    Frlist_node *p_st_node = NULL;
    cups_field_info *p_st_field = NULL;

    p_st_field = (cups_field_info *)frmalloc(sizeof(cups_field_info));
    if (p_st_field == NULL)
    {
        return FR_FAIL;
    }
    p_st_field->ui_field_index = ui_field_index;
    p_st_field->p_field_value = p_value;

    /* 创建节点 */
    p_st_node = frlist_node_create(p_st_field);
    if (p_st_node == NULL)
    {
        cups_field_free(&p_st_field);
        return FR_FAIL;
    }

    *pp_st_node = p_st_node;
    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  释放node函数指针
*  ARGS     :  p_st_node(Frlist_node)
*  RTN      :  void
*  NOTE     :
*******************************************************************************/
void cups_node_free(Frlist_node *p_st_node)
{
    if( p_st_node == NULL || p_st_node->data == NULL)
    {
        return;
    }

    cups_field_info *p_st_field = (cups_field_info *)(p_st_node->data);

    if (p_st_field->p_field_value)
    {
        frfree(p_st_field->p_field_value);
    }
    frfree(p_st_field);

    return;
}

/*******************************************************************************
*  FUNC     :  调试用
*  ARGS     :  void
*  RTN      :  void
*  NOTE     :
*******************************************************************************/
void cups_dbg(void)
{
    return;
}

/*******************************************************************************
*  FUNC     :  字符串转数字
*  ARGS     :  p_st_data (入力buff)
*           :  i_len   (数字长度)
*           :  p_ui_len (转换后的数字)
*  RTN      :  FR_FAIL      (FAIL)
*              FR_SUCC      (SUCC)
*  NOTE     :
*******************************************************************************/
int cups_str2len(char *p_len, unsigned int ui_len ,unsigned int *p_ui_len)
{
    int i_tmp = 0;
    unsigned int ui_value = 0;
    unsigned int ui_loop = 0;

    /* 转换为数字 */
    while (ui_loop < ui_len)
    {
        i_tmp = p_len[ui_loop++] - '0';
        if (i_tmp > 9 || i_tmp < 0)
        {
            return FR_FAIL;
        }
        ui_value = ui_value * 10 + i_tmp;
    }

    *p_ui_len = ui_value;
    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  字符串转数字
*  ARGS     :  p_st_data (入力buff)
*           :  i_len   (数字长度)
*           :  p_ui_len (转换后的数字)
*  RTN      :  FR_FAIL      (FAIL)
*              FR_SUCC      (SUCC)
*  NOTE     :
*******************************************************************************/
int cups_get_len(Frbyte_Packet *p_st_data
                  , unsigned int ui_len
                  , unsigned int *p_ui_len)
{
    int i_tmp = 0;
    int i_ret = FR_SUCC;
    unsigned int ui_value = 0;
    unsigned int ui_loop = 0;
    char arr_num_str[CUPS_MAX_NUM_LEN + 1] = {0};

    /* check长度 */
    if (p_st_data == NULL || ui_len > CUPS_MAX_NUM_LEN
        || ui_len > (unsigned int)bytebuff_remaining(p_st_data))
    {
        return FR_FAIL;
    }

    /* 取得长度字符串 */
    i_ret = bytebuff_get_bytes(p_st_data, arr_num_str, ui_len);
    if (i_ret != FR_SUCC)
    {
        return FR_FAIL;
    }

    /* 转换为数字 */
    while (ui_loop < ui_len)
    {
        i_tmp = arr_num_str[ui_loop++] - '0';
        if (i_tmp > 9 || i_tmp < 0)
        {
            return FR_FAIL;
        }
        ui_value = ui_value * 10 + i_tmp;
    }

    *p_ui_len = ui_value;
    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  取得字符串
*  ARGS     :  p_st_data (入力buff)
*           :  i_len   (字符串长度)
*           :  pp_value (出力字符串)
*  RTN      :  FR_FAIL      (FAIL)
*              FR_SUCC      (SUCC)
*  NOTE     :
*******************************************************************************/
int cups_get_str(Frbyte_Packet *p_st_data
                  , unsigned int ui_len
                  , char **pp_value)
{
    int i_ret = FR_SUCC;
    char *p_value = NULL;

    /* check长度 */
    if (p_st_data == NULL
        || ui_len > (unsigned int)bytebuff_remaining(p_st_data))
    {
        return FR_FAIL;
    }

    /* 取得字符串,申请足够长度，用以可能要进行的时间变换 */
    p_value = (char *)frmalloc(ui_len + 1 + 1);
    if (p_value == NULL)
    {
        return FR_FAIL;
    }
    i_ret = bytebuff_get_bytes(p_st_data, p_value, ui_len);
    if (i_ret != FR_SUCC)
    {
        return FR_FAIL;
    }
    p_value[ui_len] = '\0';

    *pp_value = p_value;
    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  取得字符串
*  ARGS     :  p_st_data (入力buff)
*           :  i_len   (字符串长度)
*           :  pp_value (出力字符串)
*  RTN      :  FR_FAIL      (FAIL)
*              FR_SUCC      (SUCC)
*  NOTE     :
*******************************************************************************/
int cups_get_binary(Frbyte_Packet *p_st_data
                     , unsigned int ui_len
                     , char **pp_value)
{
    uint8_t u8_char = 0;
    int i_ret = FR_SUCC;
    unsigned int ui_total = 0;
    unsigned int ui_loop = 0;
    char *p_value = NULL;
    char *p_tmp = NULL;

    /* check长度 */
    if (p_st_data == NULL
        || ui_len > (unsigned int)bytebuff_remaining(p_st_data))
    {
        return FR_FAIL;
    }

    /* 取得字符串,申请足够长度 */
    ui_total = 4 + 2 * ui_len;
    p_value = (char *)frmalloc(ui_total + 1);
    if (p_value == NULL)
    {
        return FR_FAIL;
    }
    if (ui_len == 0)
    {
        p_value[0] = '\0';
        *pp_value = p_value;
        return FR_SUCC;
    }

    p_tmp = p_value;
    snprintf(p_tmp, ui_total, "0X");
    p_tmp += 2;
    ui_total -= 2;

    while (ui_loop++ < ui_len)
    {
        i_ret = bytebuff_get_char(p_st_data, &u8_char);
        if (i_ret != FR_SUCC)
        {
            frfree(p_value);
            return FR_FAIL;
        }
        snprintf(p_tmp, ui_total, "%02X", u8_char);
        p_tmp += 2;
        ui_total -= 2;
    }

    *pp_value = p_value;
    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  取得Datetime
*  ARGS     :  p_st_data(数据信息)
*           :  pp_output(出力数据)
*  RTN      :  FR_SUCC  (success)
*              FR_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
int cups_get_datetime(Frbyte_Packet *p_st_data
                      , char **pp_output)
{
    int i_ret = FR_SUCC;
    char *p_date = NULL;
    char *p_data_tmp = NULL;

    /* 时间格式:MM-DDThh:mm:ssZ */
    p_date = (char *)frmalloc(10 + 5 + 1);
    if (p_date == NULL)
    {
        return FR_FAIL;
    }
    p_data_tmp = p_date;

    i_ret = bytebuff_get_bytes(p_st_data, p_data_tmp, 2);
    if (i_ret != FR_SUCC)
    {
        frfree(p_date);
        return FR_FAIL;
    }
    p_data_tmp += 2;
    *p_data_tmp = '-';
    p_data_tmp++;

    i_ret = bytebuff_get_bytes(p_st_data, p_data_tmp, 2);
    if (i_ret != FR_SUCC)
    {
        frfree(p_date);
        return FR_FAIL;
    }
    p_data_tmp += 2;
    *p_data_tmp = 'T';
    p_data_tmp++;

    i_ret = bytebuff_get_bytes(p_st_data, p_data_tmp, 2);
    if (i_ret != FR_SUCC)
    {
        frfree(p_date);
        return FR_FAIL;
    }
    p_data_tmp += 2;
    *p_data_tmp = ':';
    p_data_tmp++;

    i_ret = bytebuff_get_bytes(p_st_data, p_data_tmp, 2);
    if (i_ret != FR_SUCC)
    {
        frfree(p_date);
        return FR_FAIL;
    }
    p_data_tmp += 2;
    *p_data_tmp = ':';
    p_data_tmp++;

    i_ret = bytebuff_get_bytes(p_st_data, p_data_tmp, 2);
    if (i_ret != FR_SUCC)
    {
        frfree(p_date);
        return FR_FAIL;
    }
    p_data_tmp += 2;
    *p_data_tmp = 'Z';
    p_data_tmp++;
    *p_data_tmp = '\0';

    *pp_output = p_date;
    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  取得Datetime
*  ARGS     :  p_st_data(数据信息)
*           :  pp_output(出力数据)
*  RTN      :  FR_SUCC  (success)
*              FR_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
int cups_get_time(Frbyte_Packet *p_st_data, char **pp_output)
{
    int i_ret = FR_SUCC;
    char *p_date = NULL;
    char *p_data_tmp = NULL;

    /* 时间格式:hh:mm:ssZ */
    p_date = (char *)frmalloc(6 + 3 + 1);
    if (p_date == NULL)
    {
        return FR_FAIL;
    }
    p_data_tmp = p_date;

    i_ret = bytebuff_get_bytes(p_st_data, p_data_tmp, 2);
    if (i_ret != FR_SUCC)
    {
        frfree(p_date);
        return FR_FAIL;
    }
    p_data_tmp += 2;
    *p_data_tmp = ':';
    p_data_tmp++;

    i_ret = bytebuff_get_bytes(p_st_data, p_data_tmp, 2);
    if (i_ret != FR_SUCC)
    {
        frfree(p_date);
        return FR_FAIL;
    }
    p_data_tmp += 2;
    *p_data_tmp = ':';
    p_data_tmp++;

    i_ret = bytebuff_get_bytes(p_st_data, p_data_tmp, 2);
    if (i_ret != FR_SUCC)
    {
        frfree(p_date);
        return FR_FAIL;
    }
    p_data_tmp += 2;
    *p_data_tmp = 'Z';
    p_data_tmp++;
    *p_data_tmp = '\0';

    *pp_output = p_date;
    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  取得Datetime
*  ARGS     :  p_st_data(数据信息)
*           :  pp_output(出力数据)
*  RTN      :  FR_SUCC  (success)
*              FR_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
int cups_get_date(Frbyte_Packet *p_st_data, char **pp_output)
{
    int i_ret = FR_SUCC;
    char *p_date = NULL;
    char *p_data_tmp = NULL;

    /* 时间格式:MM-DDT */
    p_date = (char *)frmalloc(4 + 2 + 1);
    if (p_date == NULL)
    {
        return FR_FAIL;
    }
    p_data_tmp = p_date;

    i_ret = bytebuff_get_bytes(p_st_data, p_data_tmp, 2);
    if (i_ret != FR_SUCC)
    {
        frfree(p_date);
        return FR_FAIL;
    }
    p_data_tmp += 2;
    *p_data_tmp = '-';
    p_data_tmp++;

    i_ret = bytebuff_get_bytes(p_st_data, p_data_tmp, 2);
    if (i_ret != FR_SUCC)
    {
        frfree(p_date);
        return FR_FAIL;
    }
    p_data_tmp += 2;
    *p_data_tmp = 'T';
    p_data_tmp++;
    *p_data_tmp = '\0';

    *pp_output = p_date;
    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  取得bytes
*  ARGS     :  p_st_data(数据信息)
*           :  ui_len(需要取得的位数)
*           :  pp_output(出力数据)
*  RTN      :  FR_SUCC  (success)
*              FR_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
int cups_get_rate(Frbyte_Packet *p_st_data
                  , unsigned int ui_len
                  , char **pp_output)
{
    int i_ret = FR_SUCC;
    char *p_output = NULL;
    uint8_t u8_byte = 0;
    unsigned int ui_index = 0;

    /* 取得小数表示位 */
    i_ret = bytebuff_get_char(p_st_data, &u8_byte);
    if (i_ret != FR_SUCC || u8_byte < '0' || u8_byte > '9')
    {
        return FR_FAIL;
    }
    ui_index = u8_byte - '0';
    if (ui_index < 0 || ui_index > 9)
    {
        return FR_FAIL;
    }
    ui_len--;

    /* 申请足够长空间 */
    p_output = (char *)frmalloc(2 + ui_index + ui_len + 1);
    if (p_output == NULL)
    {
        return FR_FAIL;
    }

    /* 取得有效数值 */
    i_ret = bytebuff_get_bytes(p_st_data, p_output, ui_len);
    if (i_ret != FR_SUCC)
    {
        frfree(p_output);
        return FR_FAIL;
    }
    p_output[ui_len] = '\0';

    if (ui_len <= ui_index)
    {
        memmove(p_output + (ui_index - ui_len + 2), p_output, ui_len + 1);
        memcpy(p_output, "0.", 2);
        memset(p_output + 2, '0', ui_index - ui_len);
    }
    else if (ui_index)
    {
        memmove(p_output + ui_len - ui_index + 1, p_output + ui_len - ui_index, ui_index + 1);
        p_output[ui_len - ui_index] = '.';
    }

    *pp_output = p_output;
    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  创建llvar型的filed
*  ARGS     :  p_st_data(数据信息)
*           :  ui_field_idx(域号)
*           :  p_st_fields(list信息)
*  RTN      :  FR_SUCC  (success)
*              FR_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
int cups_create_llvar(Frbyte_Packet *p_st_data
                       , unsigned int ui_field_idx
                       , Frlist_header *p_st_fields)
{
    int i_ret = FR_SUCC;
    unsigned int ui_len = 0;
    char *p_value = NULL;
    Frlist_node *p_st_node = NULL;

    /* 取得长度 */
    i_ret = cups_get_len(p_st_data, 2, &ui_len);
    if (i_ret != FR_SUCC)
    {
        frdbg("get length failed!\n");
        return FR_FAIL;
    }

    /* 取得内容 */
    i_ret = cups_get_str(p_st_data, ui_len, &p_value);
    if (i_ret != FR_SUCC)
    {
        frdbg("get contents failed!\n");
        return FR_FAIL;
    }

    /* 创建节点 */
    i_ret = __cups_create_field(ui_field_idx, p_value, &p_st_node);
    if (i_ret != FR_SUCC)
    {
        frdbg("create field failed!\n");
        if (p_value)
        {
            frfree(p_value);
        }
        return i_ret;
    }

    /* 追加节点 */
    frlist_push(p_st_fields, p_st_node);
    return FR_SUCC;
}


/*******************************************************************************
*  FUNC     :  创建lllvar型的filed
*  ARGS     :  p_st_data(数据信息)
*           :  ui_field_idx(域号)
*           :  p_st_fields(list信息)
*  RTN      :  FR_SUCC  (success)
*              FR_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
int cups_create_lllvar(Frbyte_Packet *p_st_data
                       , unsigned int ui_field_idx
                       , Frlist_header *p_st_fields)
{
    int i_ret = FR_SUCC;
    unsigned int ui_len = 0;
    char *p_value = NULL;
    Frlist_node *p_st_node = NULL;

    /* 取得长度 */
    i_ret = cups_get_len(p_st_data, 3, &ui_len);
    if (i_ret != FR_SUCC)
    {
        frdbg("get length failed!\n");
        return FR_FAIL;
    }

    /* 取得内容 */
    i_ret = cups_get_str(p_st_data, ui_len, &p_value);
    if (i_ret != FR_SUCC)
    {
        frdbg("get contents failed!\n");
        return FR_FAIL;
    }

    /* 创建节点 */
    i_ret = __cups_create_field(ui_field_idx, p_value, &p_st_node);
    if (i_ret != FR_SUCC)
    {
        frdbg("create field failed!\n");
        if (p_value)
        {
            frfree(p_value);
        }
        return i_ret;
    }

    /* 追加节点 */
    frlist_push(p_st_fields, p_st_node);
    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  创建固定长度型的filed
*  ARGS     :  p_st_data(数据信息)
*           :  ui_len(需要取得的位数)
*           :  ui_field_idx(域号)
*           :  p_st_fields(list信息)
*  RTN      :  FR_SUCC  (success)
*              FR_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
int cups_create_bytes(Frbyte_Packet *p_st_data
                       , unsigned int ui_field_idx
                       , unsigned int ui_len
                       , Frlist_header *p_st_fields)
{
    int i_ret = FR_SUCC;
    char *p_value = NULL;
    Frlist_node *p_st_node = NULL;

    /* 取得内容 */
    i_ret = cups_get_str(p_st_data, ui_len, &p_value);
    if (i_ret != FR_SUCC)
    {
        frdbg("get contents failed!\n");
        return FR_FAIL;
    }

    /* 创建节点 */
    i_ret = __cups_create_field(ui_field_idx, p_value, &p_st_node);
    if (i_ret != FR_SUCC)
    {
        frdbg("create field failed!\n");
        if (p_value)
        {
            frfree(p_value);
        }
        return i_ret;
    }

    /* 追加节点 */
    frlist_push(p_st_fields, p_st_node);
    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  创建固定长度型的filed
*  ARGS     :  p_st_data(数据信息)
*           :  ui_len(需要取得的位数)
*           :  ui_field_idx(域号)
*           :  p_st_fields(list信息)
*  RTN      :  FR_SUCC  (success)
*              FR_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
int cups_create_binary(Frbyte_Packet *p_st_data
                       , unsigned int ui_field_idx
                       , unsigned int ui_len
                       , Frlist_header *p_st_fields)
{
    int i_ret = FR_SUCC;
    char *p_value = NULL;
    Frlist_node *p_st_node = NULL;

    /* 取得内容 */
    i_ret = cups_get_binary(p_st_data, ui_len, &p_value);
    if (i_ret != FR_SUCC)
    {
        frdbg("get contents failed!\n");
        return FR_FAIL;
    }

    /* 创建节点 */
    i_ret = __cups_create_field(ui_field_idx, p_value, &p_st_node);
    if (i_ret != FR_SUCC)
    {
        frdbg("create field failed!\n");
        if (p_value)
        {
            frfree(p_value);
        }
        return i_ret;
    }

    /* 追加节点 */
    frlist_push(p_st_fields, p_st_node);
    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  创建datetime型的filed
*  ARGS     :  p_st_data(数据信息)
*           :  ui_field_idx(域号)
*           :  p_st_fields(list信息)
*  RTN      :  FR_SUCC  (success)
*              FR_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
int cups_create_datetime(Frbyte_Packet *p_st_data
                          , unsigned int ui_field_idx
                          , Frlist_header *p_st_fields)
{
    int i_ret = FR_SUCC;
    char *p_value = NULL;
    Frlist_node *p_st_node = NULL;

    /* 取得内容 */
    i_ret = cups_get_datetime(p_st_data, &p_value);
    if (i_ret != FR_SUCC)
    {
        frdbg("get contents failed!\n");
        return FR_FAIL;
    }

    /* 创建节点 */
    i_ret = __cups_create_field(ui_field_idx, p_value, &p_st_node);
    if (i_ret != FR_SUCC)
    {
        frdbg("create field failed!\n");
        if (p_value)
        {
            frfree(p_value);
        }
        return i_ret;
    }

    /* 追加节点 */
    frlist_push(p_st_fields, p_st_node);
    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  创建time型的filed
*  ARGS     :  p_st_data(数据信息)
*           :  ui_field_idx(域号)
*           :  p_st_fields(list信息)
*  RTN      :  FR_SUCC  (success)
*              FR_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
int cups_create_time(Frbyte_Packet *p_st_data
                      , unsigned int ui_field_idx
                      , Frlist_header *p_st_fields)
{
    int i_ret = FR_SUCC;
    char *p_value = NULL;
    Frlist_node *p_st_node = NULL;

    /* 取得内容 */
    i_ret = cups_get_time(p_st_data, &p_value);
    if (i_ret != FR_SUCC)
    {
        frdbg("get contents failed!\n");
        return FR_FAIL;
    }

    /* 创建节点 */
    i_ret = __cups_create_field(ui_field_idx, p_value, &p_st_node);
    if (i_ret != FR_SUCC)
    {
        frdbg("create field failed!\n");
        if (p_value)
        {
            frfree(p_value);
        }
        return i_ret;
    }

    /* 追加节点 */
    frlist_push(p_st_fields, p_st_node);
    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  创建time型的filed
*  ARGS     :  p_st_data(数据信息)
*           :  ui_field_idx(域号)
*           :  p_st_fields(list信息)
*  RTN      :  FR_SUCC  (success)
*              FR_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
int cups_create_date(Frbyte_Packet *p_st_data
                      , unsigned int ui_field_idx
                      , Frlist_header *p_st_fields)
{
    int i_ret = FR_SUCC;
    char *p_value = NULL;
    Frlist_node *p_st_node = NULL;

    /* 取得内容 */
    i_ret = cups_get_date(p_st_data, &p_value);
    if (i_ret != FR_SUCC)
    {
        frdbg("get contents failed!\n");
        return FR_FAIL;
    }

    /* 创建节点 */
    i_ret = __cups_create_field(ui_field_idx, p_value, &p_st_node);
    if (i_ret != FR_SUCC)
    {
        frdbg("create field failed!\n");
        if (p_value)
        {
            frfree(p_value);
        }
        return i_ret;
    }

    /* 追加节点 */
    frlist_push(p_st_fields, p_st_node);
    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  创建固定长度型的filed
*  ARGS     :  p_st_data(数据信息)
*           :  ui_len(需要取得的位数)
*           :  ui_field_idx(域号)
*           :  p_st_fields(list信息)
*  RTN      :  FR_SUCC  (success)
*              FR_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
int cups_create_rate(Frbyte_Packet *p_st_data
                       , unsigned int ui_field_idx
                       , unsigned int ui_len
                       , Frlist_header *p_st_fields)
{
    int i_ret = FR_SUCC;
    char *p_value = NULL;
    Frlist_node *p_st_node = NULL;

    /* 取得内容 */
    i_ret = cups_get_rate(p_st_data, ui_len, &p_value);
    if (i_ret != FR_SUCC)
    {
        frdbg("get contents failed!\n");
        return FR_FAIL;
    }

    /* 创建节点 */
    i_ret = __cups_create_field(ui_field_idx, p_value, &p_st_node);
    if (i_ret != FR_SUCC)
    {
        frdbg("create field failed!\n");
        if (p_value)
        {
            frfree(p_value);
        }
        return i_ret;
    }

    /* 追加节点 */
    frlist_push(p_st_fields, p_st_node);
    return FR_SUCC;
}


/*******************************************************************************
*  FUNC     :  取得时间差(微秒)
*  ARGS     :  st_start_time(开始时间)
*           :  p_st_end_time(结束时间)
*  RTN      :  long
*  NOTE     :
*******************************************************************************/
unsigned long cups_get_interval_time(struct timeval *p_st_start_time
                                     , struct timeval *p_st_end_time)
{
    unsigned long ul_time_interval = 0;
    int i_flg = 0;

    if (p_st_start_time->tv_usec < p_st_end_time->tv_usec)
    {
        ul_time_interval = p_st_end_time->tv_usec - p_st_start_time->tv_usec;
    }
    else
    {
        ul_time_interval = 1000000 + p_st_end_time->tv_usec - p_st_start_time->tv_usec;
        i_flg = 1;
    }

    if (p_st_start_time->tv_sec + i_flg > p_st_end_time->tv_sec)
    {
        ul_time_interval = 0;
    }
    else
    {
        ul_time_interval += 1000000 * (p_st_end_time->tv_sec - p_st_start_time->tv_sec - i_flg);
    }

    return ul_time_interval;
}

/*******************************************************************************
*  FUNC     :  消除request
*  ARGS     :  pp_st_req(request)
*  RTN      :  void
*  NOTE     :
*******************************************************************************/
void cups_destroy_request(L7_req_cups **pp_st_req)
{
    if (pp_st_req == NULL || *pp_st_req == NULL)
    {
        return;
    }

    L7_req_cups *p_st_req = *pp_st_req;
    frlist_remove_all(&p_st_req->st_param, cups_node_free);
    frfree(p_st_req);

    *pp_st_req = NULL;
    return;
}

/*******************************************************************************
*  FUNC     :  消除response
*  ARGS     :  pp_st_resp(response)
*  RTN      :  void
*  NOTE     :
*******************************************************************************/
void cups_destroy_response(L7_resp_cups **pp_st_resp)
{
    if (pp_st_resp == NULL || *pp_st_resp == NULL)
    {
        return;
    }

    L7_resp_cups *p_st_resp = *pp_st_resp;
    if (p_st_resp->p_error_msg)
    {
        frfree(p_st_resp->p_error_msg);
    }
    frfree(p_st_resp);

    *pp_st_resp = NULL;
    return;
}

/*******************************************************************************
*  FUNC     :  初始化fragment
*  ARGS     :  p_st_fragment(fragment)
*  RTN      :  void
*  NOTE     :
*******************************************************************************/
void cups_init_fragment(L7_fragment_cups *p_st_fragment)
{
    if (p_st_fragment == NULL)
    {
        return;
    }

    bytebuff_free(&p_st_fragment->p_st_data);
    memset(p_st_fragment, 0x0, sizeof(L7_fragment_cups));
    return;
}

/*******************************************************************************
*  FUNC     :  销毁fragment
*  ARGS     :  pp_st_fragment(fragment)
*  RTN      :  void
*  NOTE     :
*******************************************************************************/
void cups_destroy_fragment(L7_fragment_cups **pp_st_fragment)
{
    if (pp_st_fragment == NULL || *pp_st_fragment == NULL)
    {
        return;
    }

    L7_fragment_cups *p_st_fragment = *pp_st_fragment;
    bytebuff_free(&p_st_fragment->p_st_data);
    frfree(p_st_fragment);
    return;
}

/*******************************************************************************
*  FUNC     :  根据币种取得小数点位数
*  ARGS     :  ui_currency_type(币种)
*           :  p_ui_digits(小数点位数)
*  RTN      :  void
*  NOTE     :
*******************************************************************************/
void cpus_get_digits(unsigned int ui_currency_type, unsigned int *p_ui_digits)
{
    /* 考虑到人民币应该是常用的所以放在第一个 */
    switch (ui_currency_type)
    {
        case 156:          //CNY  2  Chinese yuan   China
        case 784:          //AED  2  United Arab Emirates dirham   United Arab Emirates
        case 971:          //AFN  2  Afghan afghani   Afghanistan
        case 8:            //ALL  2  Albanian lek   Albania
        case 51:           //AMD  2  Armenian dram   Armenia
        case 532:          //ANG  2  Netherlands Antillean guilder   Cura?ao (CW),  Sint Maarten (SX)
        case 973:          //AOA  2  Angolan kwanza   Angola
        case 32:           //ARS  2  Argentine peso   Argentina
        case 36:           //AUD  2  Australian dollar   Australia,  Christmas Island (CX),  Cocos (Keeling) Islands (CC),  Heard Island and McDonald Islands (HM),  Kiribati (KI),  Nauru (NR),  Norfolk Island (NF),  Tuvalu (TV),  Australian Antarctic Territory
        case 533:          //AWG  2  Aruban florin   Aruba
        case 944:          //AZN  2  Azerbaijani manat   Azerbaijan
        case 977:          //BAM  2  Bosnia and Herzegovina convertible mark   Bosnia and Herzegovina
        case 52:           //BBD  2  Barbados dollar   Barbados
        case 50:           //BDT  2  Bangladeshi taka   Bangladesh
        case 975:          //BGN  2  Bulgarian lev   Bulgaria
        case 60:           //BMD  2  Bermudian dollar   Bermuda
        case 96:           //BND  2  Brunei dollar   Brunei, auxiliary in  Singapore (SG)
        case 68:           //BOB  2  Boliviano   Bolivia
        case 984:          //BOV  2  Bolivian Mvdol (funds code)   Bolivia
        case 986:          //BRL  2  Brazilian real   Brazil
        case 44:           //BSD  2  Bahamian dollar   Bahamas
        case 64:           //BTN  2  Bhutanese ngultrum   Bhutan
        case 72:           //BWP  2  Botswana pula   Botswana
        case 84:           //BZD  2  Belize dollar   Belize
        case 124:          //CAD  2  Canadian dollar   Canada
        case 976:          //CDF  2  Congolese franc   Democratic Republic of the Congo
        case 947:          //CHE  2  WIR Euro (complementary currency)    Switzerland
        case 756:          //CHF  2  Swiss franc    Switzerland,  Liechtenstein (LI)
        case 948:          //CHW  2  WIR Franc (complementary currency)    Switzerland
        case 170:          //COP  2  Colombian peso   Colombia
        case 970:          //COU  2   Unidad de Valor Real (UVR) (funds code)[7]   Colombia
        case 188:          //CRC  2  Costa Rican colon   Costa Rica
        case 931:          //CUC  2  Cuban convertible peso   Cuba
        case 192:          //CUP  2  Cuban peso   Cuba
        case 203:          //CZK  2  Czech koruna   Czech Republic
        case 208:          //DKK  2  Danish krone   Denmark,  Faroe Islands (FO),  Greenland (GL)
        case 214:          //DOP  2  Dominican peso   Dominican Republic
        case 12:           //DZD  2  Algerian dinar   Algeria
        case 818:          //EGP  2  Egyptian pound   Egypt, auxiliary in  Gaza Strip
        case 232:          //ERN  2  Eritrean nakfa   Eritrea
        case 230:          //ETB  2  Ethiopian birr   Ethiopia
        case 978:          //EUR  2  Euro   Akrotiri and Dhekelia,  Andorra (AD),  Austria (AT),  Belgium (BE),  Cyprus (CY),  Estonia (EE),  Finland (FI),  France (FR),  Germany (DE),  Greece (GR),  Guadeloupe (GP),  Ireland (IE),  Italy (IT),  Kosovo,  Latvia (LV),  Lithuania (LT),  Luxembourg (LU),  Malta (MT),  Martinique (MQ),  Mayotte (YT),  Monaco (MC),  Montenegro (ME),  Netherlands (NL),  Portugal (PT),  Réunion (RE),  Saint Barthélemy (BL),  Saint Pierre and Miquelon (PM),  San Marino (SM),  Slovakia (SK),  Slovenia (SI),  Spain (ES),   Vatican City (VA); see Eurozone
        case 242:          //FJD  2  Fiji dollar   Fiji
        case 238:          //FKP  2  Falkland Islands pound   Falkland Islands (pegged to GBP 1:1)
        case 826:          //GBP  2  Pound sterling   United Kingdom, the  Isle of Man (IM, see Manx pound),  Jersey (JE, see Jersey pound),  Guernsey (GG, see Guernsey pound),  South Georgia and the South Sandwich Islands (GS),  British Indian Ocean Territory (IO) (also uses USD),  Tristan da Cunha (SH-TA), and  British Antarctic Territory
        case 981:          //GEL  2  Georgian lari   Georgia (except  Abkhazia (GE-AB) and  South Ossetia)
        case 936:          //GHS  2  Ghanaian cedi   Ghana
        case 292:          //GIP  2  Gibraltar pound   Gibraltar (pegged to GBP 1:1)
        case 270:          //GMD  2  Gambian dalasi   Gambia
        case 320:          //GTQ  2  Guatemalan quetzal   Guatemala
        case 328:          //GYD  2  Guyanese dollar   Guyana
        case 344:          //HKD  2  Hong Kong dollar   Hong Kong,  Macao (MO)
        case 340:          //HNL  2  Honduran lempira   Honduras
        case 191:          //HRK  2  Croatian kuna   Croatia
        case 332:          //HTG  2  Haitian gourde   Haiti
        case 348:          //HUF  2  Hungarian forint   Hungary
        case 360:          //IDR  2  Indonesian rupiah   Indonesia
        case 376:          //ILS  2  Israeli new shekel   Israel,  State of Palestine (PS)[8]
        case 356:          //INR  2  Indian rupee   India, Bhutan,    Nepal ,  Zimbabwe
        case 364:          //IRR  2  Iranian rial   Iran
        case 388:          //JMD  2  Jamaican dollar   Jamaica
        case 404:          //KES  2  Kenyan shilling   Kenya
        case 417:          //KGS  2  Kyrgyzstani som   Kyrgyzstan
        case 116:          //KHR  2  Cambodian riel   Cambodia
        case 408:          //KPW  2  North Korean won   North Korea
        case 136:          //KYD  2  Cayman Islands dollar   Cayman Islands
        case 398:          //KZT  2  Kazakhstani tenge   Kazakhstan
        case 418:          //LAK  2  Lao kip   Laos
        case 422:          //LBP  2  Lebanese pound   Lebanon
        case 144:          //LKR  2  Sri Lankan rupee   Sri Lanka
        case 430:          //LRD  2  Liberian dollar   Liberia
        case 426:          //LSL  2  Lesotho loti   Lesotho
        case 504:          //MAD  2  Moroccan dirham   Morocco
        case 498:          //MDL  2  Moldovan leu   Moldova (except  Transnistria)
        case 807:          //MKD  2  Macedonian denar   Macedonia
        case 104:          //MMK  2  Myanmar kyat   Myanmar
        case 496:          //MNT  2  Mongolian t?gr?g   Mongolia
        case 446:          //MOP  2  Macanese pataca   Macao
        case 480:          //MUR  2  Mauritian rupee   Mauritius
        case 462:          //MVR  2  Maldivian rufiyaa   Maldives
        case 454:          //MWK  2  Malawian kwacha   Malawi
        case 484:          //MXN  2  Mexican peso   Mexico
        case 979:          //MXV  2  Mexican Unidad de Inversion (UDI) (funds code)   Mexico
        case 458:          //MYR  2  Malaysian ringgit   Malaysia
        case 943:          //MZN  2  Mozambican metical   Mozambique
        case 516:          //NAD  2  Namibian dollar   Namibia
        case 566:          //NGN  2  Nigerian naira   Nigeria
        case 558:          //NIO  2  Nicaraguan córdoba   Nicaragua
        case 578:          //NOK  2  Norwegian krone   Norway,  Svalbard and  Jan Mayen (SJ),  Bouvet Island (BV),  Queen Maud Land,  Peter I Island
        case 524:          //NPR  2  Nepalese rupee     Nepal
        case 554:          //NZD  2  New Zealand dollar   New Zealand,  Cook Islands (CK),  Niue (NU),  Pitcairn Islands (PN; see also Pitcairn Islands dollar),  Tokelau (TK),  Ross Dependency
        case 590:          //PAB  2  Panamanian balboa   Panama
        case 604:          //PEN  2  Peruvian Sol   Peru
        case 598:          //PGK  2  Papua New Guinean kina   Papua New Guinea
        case 608:          //PHP  2  Philippine peso   Philippines
        case 586:          //PKR  2  Pakistani rupee   Pakistan
        case 985:          //PLN  2  Polish z?oty   Poland
        case 634:          //QAR  2  Qatari riyal   Qatar
        case 946:          //RON  2  Romanian leu   Romania
        case 941:          //RSD  2  Serbian dinar   Serbia
        case 643:          //RUB  2  Russian ruble   Russia,  Abkhazia (GE-AB),  South Ossetia,  Crimea
        case 682:          //SAR  2  Saudi riyal   Saudi Arabia
        case 90:           //SBD  2  Solomon Islands dollar   Solomon Islands
        case 690:          //SCR  2  Seychelles rupee   Seychelles
        case 938:          //SDG  2  Sudanese pound   Sudan
        case 752:          //SEK  2  Swedish krona/kronor   Sweden
        case 702:          //SGD  2  Singapore dollar   Singapore, auxiliary in  Brunei (BN)
        case 654:          //SHP  2  Saint Helena pound   Saint Helena (SH-SH),  Ascension Island (SH-AC) (pegged to GBP 1:1)
        case 694:          //SLL  2  Sierra Leonean leone   Sierra Leone
        case 706:          //SOS  2  Somali shilling   Somalia (except  Somaliland)
        case 968:          //SRD  2  Surinamese dollar   Suriname
        case 728:          //SSP  2  South Sudanese pound   South Sudan
        case 678:          //STD  2  S?o Tomé and Príncipe dobra   S?o Tomé and Príncipe
        case 760:          //SYP  2  Syrian pound   Syria
        case 748:          //SZL  2  Swazi lilangeni   Swaziland
        case 764:          //THB  2  Thai baht   Thailand ,  Cambodia ,  Myanmar ,  Laos
        case 972:          //TJS  2  Tajikistani somoni   Tajikistan
        case 934:          //TMT  2  Turkmenistani manat   Turkmenistan
        case 776:          //TOP  2  Tongan pa?anga   Tonga
        case 949:          //TRY  2  Turkish lira   Turkey ,  Northern Cyprus
        case 780:          //TTD  2  Trinidad and Tobago dollar   Trinidad and Tobago
        case 901:          //TWD  2  New Taiwan dollar   Taiwan
        case 834:          //TZS  2  Tanzanian shilling   Tanzania
        case 980:          //UAH  2  Ukrainian hryvnia   Ukraine
        case 840:          //USD  2  United States dollar   United States,  American Samoa (AS),  Barbados (BB) (as well as Barbados Dollar),  Bermuda (BM) (as well as Bermudian Dollar),  British Indian Ocean Territory (IO) (also uses GBP),  British Virgin Islands (VG), Caribbean Netherlands (BQ - Bonaire, Sint Eustatius and Saba),  Ecuador (EC),  El Salvador (SV),  Guam (GU),  Haiti (HT),  Marshall Islands (MH),  Federated States of Micronesia (FM),  Northern Mariana Islands (MP),  Palau (PW),  Panama (PA),  Puerto Rico (PR),  Timor-Leste (TL),  Turks and Caicos Islands (TC),  U.S. Virgin Islands (VI),  Zimbabwe (ZW),
        case 997:          //USN  2  United States dollar (next day) (funds code)   United States
        case 998:          //USS  2  United States dollar (same day) (funds code)[10]   United States
        case 858:          //UYU  2  Uruguayan peso   Uruguay
        case 860:          //UZS  2  Uzbekistan som   Uzbekistan
        case 937:          //VEF  2  Venezuelan bolívar   Venezuela
        case 882:          //WST  2  Samoan tala   Samoa
        case 951:          //XCD  2  East Caribbean dollar   Anguilla (AI),  Antigua and Barbuda (AG),  Dominica (DM),  Grenada (GD),  Montserrat (MS),  Saint Kitts and Nevis (KN),  Saint Lucia (LC),  Saint Vincent and the Grenadines (VC)
        case 886:          //YER  2  Yemeni rial   Yemen
        case 710:          //ZAR  2  South African rand   South Africa
        case 967:          //ZMW  2  Zambian kwacha   Zambia
            *p_ui_digits = 2;
            break;

        case 969:        //MGA  1   Malagasy ariary   Madagascar
        case 478:        //MRO  1   Mauritanian ouguiya   Mauritania
            *p_ui_digits = 1;
            break;

        case 48:           //BHD  3  Bahraini dinar   Bahrain
        case 368:          //IQD  3  Iraqi dinar   Iraq
        case 400:          //JOD  3  Jordanian dinar   Jordan, auxiliary in  West Bank
        case 414:          //KWD  3  Kuwaiti dinar   Kuwait
        case 434:          //LYD  3  Libyan dinar   Libya
        case 512:          //OMR  3  Omani rial   Oman
        case 788:          //TND  3  Tunisian dinar   Tunisia
            *p_ui_digits = 3;
            break;

        case 990:          //CLF  4  Unidad de Fomento (funds code)   Chile
            *p_ui_digits = 4;
            break;

        default:
            *p_ui_digits = 0;
            break;
    }

    return;
}

/*******************************************************************************
*  FUNC     :  删除前导零
*  ARGS     :  p_num_str(元数据)
*  RTN      :
*  NOTE     :
*******************************************************************************/
void cups_ltrim_leading_zero(char *p_num_str)
{
    unsigned int ui_len = 0;
    unsigned int ui_loop = 0;

    /* 去掉前导零 */
    ui_len = strlen(p_num_str);
    /* remove the left space '\t' */
    for (ui_loop = 0; ui_loop < ui_len; ui_loop++)
    {
        if (p_num_str[ui_loop] != '0' ||
            (p_num_str[ui_loop] == '0' && p_num_str[ui_loop + 1] == '.'))
        {
            break;
        }
    }

    if (ui_loop > 0)
    {
        memmove(p_num_str, p_num_str + ui_loop, ui_len - ui_loop + 1 );
    }
    return;
}

/*******************************************************************************
*  FUNC     :  取得金额
*  ARGS     :  pp_currency(元数据)
*           :  ui_digits(小数点位数)
*  RTN      :
*  NOTE     :
*******************************************************************************/
int cups_get_currency(char **pp_currency, unsigned int ui_digits)
{
    if (pp_currency == NULL || *pp_currency == NULL || **pp_currency == '\0')
    {
        return APM_L7_ANALYZE_SUCC;
    }

    if (ui_digits == 0)
    {
        cups_ltrim_leading_zero(*pp_currency);
        return APM_L7_ANALYZE_SUCC;
    }

    char *p_tmp = NULL;
    char *p_currency = *pp_currency;
    unsigned int ui_len = strlen(p_currency);

    p_tmp = (char *)frmalloc(ui_len + ui_digits + 10);
    if (p_tmp == NULL)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    if (ui_len <= ui_digits)
    {
        snprintf(p_tmp, ui_len + ui_digits + 10, "0.");
        memset(p_tmp + 2, '0', ui_digits - ui_len);
        snprintf(p_tmp + 2 + ui_digits - ui_len
                , ui_len + ui_digits + 10 - 2 - ui_digits + ui_len
                , "%s", p_currency);
    }
    else
    {
        memcpy(p_tmp, p_currency, ui_len - ui_digits);
        p_tmp[ui_len - ui_digits] = '.';
        memcpy(p_tmp + ui_len - ui_digits + 1
              , p_currency + ui_len - ui_digits
              , ui_digits + 1);
    }

    frfree(p_currency);
    cups_ltrim_leading_zero(p_tmp);
    *pp_currency = p_tmp;
    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  取得金额
*  ARGS     :  pp_currency(元数据)
*           :  ui_digits(小数点位数)
*  RTN      :
*  NOTE     :
*******************************************************************************/
int cups_get_currency2(char **pp_currency, unsigned int ui_digits)
{
    if (pp_currency == NULL || *pp_currency == NULL || **pp_currency == '\0')
    {
        return APM_L7_ANALYZE_SUCC;
    }

    char p_currency_type = 0;
    char *p_tmp = NULL;
    char *p_currency = *pp_currency;
    unsigned int ui_len = 0;
    unsigned int ui_loop = 0;

    p_currency_type = *p_currency;
    p_currency++;
    ui_len = strlen(p_currency);

    if (ui_digits == 0)
    {
        cups_ltrim_leading_zero(p_currency);
        return APM_L7_ANALYZE_SUCC;
    }

    p_tmp = (char *)frmalloc(ui_len + ui_digits + 10 + 1);
    if (p_tmp == NULL)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    *p_tmp = p_currency_type;
    p_tmp++;
    if (ui_len <= ui_digits)
    {
        snprintf(p_tmp, ui_len + ui_digits + 10, "0.");
        memset(p_tmp + 2, '0', ui_digits - ui_len);
        snprintf(p_tmp + 2 + ui_digits - ui_len
                , ui_len + ui_digits + 10 - 2 - ui_digits + ui_len
                , "%s", p_currency);
    }
    else
    {
        memcpy(p_tmp, p_currency, ui_len - ui_digits);
        p_tmp[ui_len - ui_digits] = '.';
        memcpy(p_tmp + ui_len - ui_digits + 1
              , p_currency + ui_len - ui_digits
              , ui_digits + 1);
    }

    frfree(*pp_currency);
    cups_ltrim_leading_zero(p_tmp);
    *pp_currency = --p_tmp;
    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  取得type name
*  ARGS     :  p_type_code(code)
*           :  pp_type_name(name)
*  RTN      :
*  NOTE     :
*******************************************************************************/
int cups_get_type_name(char *p_type_code, char **pp_type_name)
{
    int i_ret = FR_SUCC;
    char *p_type_name = NULL;
    unsigned int ui_type_code = 0;
    i_ret = cups_str2len(p_type_code, strlen(p_type_code), &ui_type_code);
    if (i_ret != FR_SUCC)
    {
        return FR_FAIL;
    }

    switch (ui_type_code)
    {
        case 300000:
        case 301000:
        case 302000:
        case 303000:
        case 304000:
            p_type_name = frstrdup("余额查询");
            break;

        case 30000:
        case 31000:
        case 32000:
        case 33000:
        case 34000:
            p_type_name = frstrdup("预授权/预授权冲正");
            break;

        case 200000:
        case 201000:
        case 202000:
        case 203000:
        case 204000:
            p_type_name = frstrdup("预授权撤销/预授权撤销冲正");
            break;

        case 0:
        case 1000:
        case 2000:
        case 3000:
        case 4000:
            p_type_name = frstrdup("预授权完成（请求）/冲正/退单/再请款");
            break;

       //case 0:
       //case 1000:
       //case 2000:
       //case 3000:
       //case 4000:
       //    p_type_name = frstrdup(" 授权/MOTO预授权/冲正");
       //    break;

       //case 200000:
       //case 201000:
       //case 202000:
       //case 203000:
       //case 204000:
       //    p_type_name = frstrdup("授权撤销/MOTO预授权撤销/冲正");
       //    break;

      //case 000000:
      //case 001000:
      //case 002000:
      //case 003000:
      //case 004000:
      //    p_type_name = frstrdup("消费/脱机消费通知/MOTO消费/代收/冲正/退单/再请款");
      //    break;

      // case 000000:
      // case 001000:
      // case 002000:
      // case 003000:
      // case 004000:
      //     p_type_name = frstrdup("预授权完成（ 请求、 通知）/结算通知/手工预授权完成/MOTO预授权完成 （请求、 通知）/MOTO结算通知/退单/再请款");
      //     break;

      // case 200000:
      // case 201000:
      // case 202000:
      // case 203000:
      // case 204000:
      //     p_type_name = frstrdup("消费撤销/MOTO消费撤销/代收撤销/冲正");
      //     break;

      // case 200000:
      // case 201000:
      // case 202000:
      // case 203000:
      // case 204000:
      //     p_type_name = frstrdup("退货");
      //     break;

      // case 200000:
      // case 201000:
      // case 202000:
      // case 203000:
      // case 204000:
      //     p_type_name = frstrdup("预授权完成撤销/冲正");
      //     break;

        case 10000:
        case 11000:
        case 12000:
        case 13000:
        case 14000:
            p_type_name = frstrdup("取现/冲正/退单/再请款");
            break;

        case 210000:
        case 211000:
        case 212000:
        case 213000:
        case 214000:
            p_type_name = frstrdup("存款");
            break;

       //case 210000:
       //case 211000:
       //case 212000:
       //case 213000:
       //case 214000:
       //    p_type_name = frstrdup("存款确认");
       //    break;

        case 170000:
        case 171000:
        case 172000:
        case 173000:
        case 174000:
            p_type_name = frstrdup("存款撤销/IC卡电子现金应用的现金充值撤销");
            break;

        case 400000:
        case 401000:
        case 402000:
        case 403000:
        case 404000:
            p_type_name = frstrdup("转账（转入方付费、转出方付费）");
            break;

        case 460000:
        case 461000:
        case 462000:
        case 463000:
        case 464000:
            p_type_name = frstrdup("转出（转入方付费、转出方付费）");
            break;

        case 470000:
        case 471000:
        case 472000:
        case 473000:
        case 474000:
            p_type_name = frstrdup("转入（转入方付费、转出方付费）");
            break;

       //case 470000:
       //case 471000:
       //case 472000:
       //case 473000:
       //case 474000:
       //    p_type_name = frstrdup("转入确认（转入方付费、转出方付费）");
       //    break;

        case 220000:
        case 221000:
        case 222000:
        case 223000:
        case 224000:
            p_type_name = frstrdup("贷记调整");
            break;

      //case 020000:
      //case 021000:
      //case 022000:
      //case 023000:
      //case 024000:
      //    p_type_name = frstrdup("请款/退单/再请款");
      //    break;

        case 600000:
        case 601000:
        case 602000:
        case 603000:
        case 604000:
            p_type_name = frstrdup("基于PBOC电子钱包/存折标准和IC卡电子现金应用额指定账户圈存");
            break;

        case 620000:
        case 621000:
        case 622000:
        case 623000:
        case 624000:
            p_type_name = frstrdup("基于PBOC电子钱包/存折标准和IC卡电子现金应用的非指定账户转账圈存");
            break;

        case 630000:
        case 631000:
        case 632000:
        case 633000:
        case 634000:
            p_type_name = frstrdup("基于PBOC电子钱包/存折标准和IC卡电子现金应用的现金充值/磁条卡现金充值");
            break;

        case 640000:
        case 641000:
        case 642000:
        case 643000:
        case 644000:
            p_type_name = frstrdup("基于PBOC电子钱包/存折标准和IC卡电子现金应用的非指定账户转出圈存");
            break;

        case 650000:
        case 651000:
        case 652000:
        case 653000:
        case 654000:
            p_type_name = frstrdup("基于PBOC电子钱包/存折标准和IC卡电子现金应用的非指定账户转入圈存");
            break;

        case 190000:
        case 191000:
        case 192000:
        case 193000:
        case 194000:
            p_type_name = frstrdup("收/付费-借记");
            break;

        case 290000:
        case 291000:
        case 292000:
        case 293000:
        case 294000:
            p_type_name = frstrdup("收/付费-贷记");
            break;

      //case 220000:
      //case 221000:
      //case 222000:
      //case 223000:
      //case 224000:
      //    p_type_name = frstrdup("差错例外");
      //    break;

        case 270000:
        case 271000:
        case 272000:
        case 273000:
        case 274000:
            p_type_name = frstrdup("预借现金（Cash Advance）撤销");
            break;

        case 240000:
        case 241000:
        case 242000:
        case 243000:
        case 244000:
            p_type_name = frstrdup("汇款验证/汇款");
            break;

      //case 290000:
      //case 291000:
      //case 292000:
      //case 293000:
      //case 294000:
      //    p_type_name = frstrdup("代付/代付确认");
      //    break;

        case 330000:
        case 331000:
        case 332000:
        case 333000:
        case 334000:
            p_type_name = frstrdup("账户验证");
            break;

        case 890000:
        case 891000:
        case 892000:
        case 893000:
        case 894000:
            p_type_name = frstrdup("建立委托");
            break;

        case 920000:
        case 921000:
        case 922000:
        case 923000:
        case 924000:
            p_type_name = frstrdup("解除委托");
            break;

         default:
            p_type_name = frstrdup("UNKNOW");
            break;
    }

    *pp_type_name = p_type_name;
    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  取得channel
*  ARGS     :  p_reserved(reserved字段)
*           :  pp_channel(name)
*  RTN      :
*  NOTE     :
*******************************************************************************/
int cups_get_channel(char *p_reserved, char **pp_channel)
{
    int i_ret = FR_SUCC;
    char *p_channel = NULL;
    unsigned int ui_channel = 0;

    if (p_reserved == NULL || strlen(p_reserved) < 10)
    {
        return FR_FAIL;
    }

    i_ret = cups_str2len(p_reserved + 8, 2, &ui_channel);
    if (i_ret != FR_SUCC)
    {
        return FR_FAIL;
    }

    switch (ui_channel)
    {
         case 0:
             p_channel = frstrdup("未知");
             break;

         case 1:
             p_channel = frstrdup("自动柜员机");
             break;

         case 3:
             p_channel = frstrdup("有线销售点终端(POS)");
             break;

         case 5:
            p_channel = frstrdup("多媒体终端");
             break;

         case 6:
             p_channel = frstrdup("银行柜台和柜面");
             break;

         case 7:
             p_channel = frstrdup("个人电脑");
             break;

         case 8:
            p_channel = frstrdup("手机设备");
             break;

         case 9:
             p_channel = frstrdup("I型固定电话");
             break;

         case 10:
             p_channel = frstrdup("基于 PBOC 电子钱包/存折标准的交易终端");
             break;

         case 11:
             p_channel = frstrdup("无线销售点终端（移动 POS）");
             break;

         case 12:
             p_channel = frstrdup("中国银联公共服务平台");
             break;

         case 13:
             p_channel = frstrdup("农民工银行卡特色服务");
             break;

         case 14:
             p_channel = frstrdup("商户系统");
             break;

         case 15:
             p_channel = frstrdup("第三方机构系统");
             break;

         case 16:
             p_channel = frstrdup("数字机顶盒");
             break;

         case 17:
             p_channel = frstrdup("II 型固定电话");
             break;

         case 20:
             p_channel = frstrdup("批量文件处理系统");
             break;

         default:
             p_channel = frstrdup("保留使用");
             break;
    }

    *pp_channel = p_channel;
    return FR_SUCC;
}
